﻿using System;

namespace ZquenceStudio3Host.DspPlugins.Synthesizers.Nodesizer.Engine.Modules.HighLevel
{
    [ModuleDisplay("Glide")]
    public class GlideModule : BaseModule
    {
        private double mCurrentValue;
        private double mSpeed;

        public readonly ModuleInput Input;
        public readonly ModuleOutput Output;

        public readonly InputModuleParameter ParameterSpeed;

        public double Speed { get; set; }

        public GlideModule(ModuleManager manager)
            : base(manager)
        {
            AddInput(Input = new ModuleInput("In", "Input", IOType.Audio, this));
            AddOutput(Output = new ModuleOutput("Out", "Output", IOType.Audio, this));

            ParameterSpeed = new InputModuleParameter(this, "Gld", 0.1, IOType.Audio);
            ParameterSpeed.Label = "Speed";
            ParameterSpeed.MinValue = 0.001;
            ParameterSpeed.MaxValue = 1;
            ParameterSpeed.DirectGet += delegate { return mSpeed; };
            ParameterSpeed.DirectSet += delegate (double value)
            {
                mSpeed = value;
                Speed = value * 0.9 * 0.1;
            };
            ParameterSpeed.RawValue = 0.2;
            AddModuleParameter(ParameterSpeed);
        }

        public override void Process()
        {
            if (Input.IsConnected)
            {
                double[] inBuffer = Input.FromOutput.AudioBuffer.Buffer;
                double[] outBuffer = Output.AudioBuffer.Buffer;
                int length = Input.FromOutput.AudioBuffer.Buffer.Length;

                double currentValue = mCurrentValue;

                for (int i = 0; i < length; i++)
                {
                    double value = inBuffer[i];

                    double powFreq = 1.015;

                    if (currentValue > value)
                    {
                        double speed2 = Math.Pow(powFreq, currentValue) * Speed;
                        currentValue -= speed2;
                        if (currentValue < value)
                        {
                            currentValue = value;
                        }
                    }
                    else if (currentValue < value)
                    {
                        double speed2 = Math.Pow(powFreq, currentValue) * Speed;
                        currentValue += speed2;
                        if (currentValue > value)
                        {
                            currentValue = value;
                        }
                    }

                    outBuffer[i] = currentValue;
                }

                mCurrentValue = currentValue;
            }
        }
    }
}
